package cn.lj.factory;

import cn.lj.service.AccountService;
import cn.lj.utils.TransactionManager;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author lj
 * @Description:用于创建Service的代理对象的工厂
 * @date 2020-12-02 13:41
 * @QQ 851477108
 */


public class BeanFactory {
    private AccountService accountService;

    private TransactionManager txManager;

    public void setTxManager(TransactionManager txManager) {
        this.txManager = txManager;
    }


    public final void setAccountService(AccountService accountService) {
        this.accountService = accountService;
    }

    /**
     * 代替get方法,获取Service代理对象
     * @return
     */
    public AccountService getAccountService(){
        //动态代理增强对象
                /*
            三个参数：
                1. 类加载器：真实对象.getClass().getClassLoader()
                2. 接口数组：真实对象.getClass().getInterfaces()
                3. 处理器：new InvocationHandler()
         */
        AccountService proxyObject = (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(),
                accountService.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * 代理逻辑编写的方法：代理对象调用的所有方法都会触发该方法执行
                     * @param proxy:代理对象
                     * @param method:代理对象调用的方法，被封装为的对象
                     * @param args:代理对象调用的方法时，传递的实际参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if ("test".equals(method.getName())) {
                            return method.invoke(accountService, args);
                        }
                        try {
                            //1.开启事务
                            txManager.beginTransaction();
                            //2.执行操作
                            Object rtValue = method.invoke(accountService, args);
                            //3.提交事务
                            txManager.commit();
                            //4.返回结果
                            return rtValue;
                        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                            //5.回滚操作
                            txManager.rollback();
                            throw new RuntimeException(e);
                        } finally {
                            //6.释放连接
                            txManager.release();
                        }
                    }
                });
        return proxyObject;
    }
}
